<template>
  <div ref="hdwrapper">
    <ul>
      <slot></slot>
    </ul>
  </div>
</template>
<script>
/**
 * 详见 hdScrollBar.vue 内部说明
 */
export default {
  name: 'hd-scroll-panel',
  data() {
    return {
      tabPanels: []
    }
  },
  props: {
    value: {}
  },
  watch: {
    value(val) {
      // 如果是点击操作执行跳转,否则不处理
      if (val.active) {
        this.gotoItem(val)
      }
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.tabPanels = this.$children.filter(item => item.$options.name === 'hd-scroll-panel-item')
      // 发生滚动时候进行执行 阀值
      window.onscroll = this.throttle(this.handleScroll, 30)
    })
  },
  methods: {
    gotoItem(valData) {
      let val = valData.link
      // 获取子节点
      this.tabPanels.forEach((panel, index) => {
        if (panel.$el.id === ('link' + val)) {
          this.$scrollTo(panel.$el, 500, {offset: -45})
        }
      })
    },
    handleScroll() {
      // 如果内容区域滚动溢出,开始执行计算导航,否则导航都是第一个
      if (this.$refs.hdwrapper) {
        if (this.$refs.hdwrapper.getBoundingClientRect().top < 0) {
          this.tabPanels.forEach((panel, index) => {
            if (panel.$el.getBoundingClientRect().top - 55 < 0) {
              // 如果有下一级元素,获取下一级元素,看看下一级元素距离顶部距离是否大于零,如果大于零,说明没有进入到下一个tab
              if ((index + 1) < this.tabPanels.length) {
                if (this.tabPanels[index + 1].$el.getBoundingClientRect().top > 0) {
                  let k = panel.$el.id.match(/link(\S*)/)[1]
                  this.$emit('change', {link: k, active: false})
                }
              } else {
                // 如果没有下级元素,表示最后一个
                let k = panel.$el.id.match(/link(\S*)/)[1]
                this.$emit('change', {link: k, active: false})
              }
            }
          })
        } else {
          let k = this.tabPanels[0].$el.id.match(/link(\S*)/)[1]
          this.$emit('change', {link: k, active: false})
        }
      }
    },
    /**
     * 函数节流方法
     * @param Function fn 延时调用函数
     * @param Number delay 延迟多长时间
     * @param Number atleast 至少多长时间触发一次
     * @return Function 延迟执行的方法
     */
    throttle (fn, delay, atleast) {
      var timer = null;
      var previous = null;
      return function () {
        var now = +new Date();
        if (!previous) previous = now;
        if (now - previous > atleast) {
          fn();
          // 重置上一次开始时间为本次结束时间
          previous = now;
        } else {
          clearTimeout(timer);
          timer = setTimeout(function() {
            fn();
          }, delay);
        }
      }
    }
  }
}
</script>
<style lang="stylus" scoped>

</style>

